package controller

import (
	"path"
	"strconv"
	"strings"

	"device-admin/config"
	"device-admin/internal/app/web/service/location"
	"device-admin/internal/dal"
	"device-admin/internal/define"
	"device-admin/internal/models"
	"device-admin/internal/pkg/upload"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/response"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

type Location struct{}

// SetToken 设置商场的TOKEN
func (Location) SetToken(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}
	err = location.SetToken(params.ID)
	if err == nil {
		response.JSON(c, nil, errorx.New("配置商场token成功！", 0))
	} else {
		response.JSON(c, nil, errorx.New("非法操作", -1))
		return
	}
}

// Disable 禁用商场的TOKEN
func (Location) DisableToken(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}
	err = location.DisableToken(params.ID)
	if err == nil {
		response.JSON(c, nil, errorx.New("禁用成功！", 0))
	} else {
		response.JSON(c, nil, errorx.New("非法操作", -1))
		return
	}
}

// SetRobotIds 设置商场可查看的设备
func (Location) SetRobotIds(c *gin.Context) {
	var params struct {
		ID       string `json:"id"`
		RobotIds string `json:"robot_ids"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}
	err = location.SetRobotIds(params.ID, params.RobotIds)
	if err == nil {
		response.JSON(c, nil, errorx.New("设置商场可查看机器成功！", 0))
	} else {
		response.JSON(c, nil, errorx.New("设置失败！", -1))
		return
	}
}

// SetLocationPoints 商场积分对接
func (Location) SetLocationPoints(c *gin.Context) {
	var params struct {
		LocationID      string  `json:"location_id"`
		PointsID        string  `json:"points_id"`
		MallID          string  `json:"mall_id"`
		Sort            int64   `json:"sort"`
		BackgroundImage string  `json:"background_image"`
		PointsValue     float64 `json:"points_value"` //积分比例 【1:x】 //1元的积分价值
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.SetLocationPoints(params.LocationID, params.PointsID, params.MallID, params.Sort, params.BackgroundImage, params.PointsValue)
	response.JSON(c, nil, err)
}

// SetNavURL 设置位置的外部导航链接
func (Location) SetNavURL(c *gin.Context) {
	var params struct {
		LocationID string `json:"location_id"`
		NavURL     string `json:"nav_url"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.SetNavURL(params.LocationID, params.NavURL)
	response.JSON(c, nil, err)
}

// AllPointsType 所有积分类型
func (Location) AllPointsType(c *gin.Context) {
	var dataMap = make(map[string]string)
	for k, v := range define.PointsType {
		dataMap[k] = v
	}
	response.JSON(c, dataMap, nil)
}

// All 全部位置
func (Location) All(c *gin.Context) {
	list, total := location.AllLocation(
		c.Request.Context(),
		c.Query("province_id"),
		c.Query("city_id"),
		c.Query("district_id"),
	)
	response.JSON(c, map[string]interface{}{
		"list":  list,
		"total": total,
	}, nil)
}

// List 位置列表
func (Location) List(c *gin.Context) {
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	list, total := location.LocationList(
		c.Query("name"),
		c.Query("province_id"), c.Query("city_id"), c.Query("district_id"),
		page, limit,
	)
	// 位置包含的楼层
	// 位置包含的精准位置
	if total == 0 {
		response.JSON(c, gin.H{
			"list":  []string{},
			"total": 0,
		}, nil)
	} else {
		response.JSON(c, gin.H{
			"list":  list,
			"total": total,
		}, nil)
	}
}

// AreaList 位置区域列表
// 结果为省市及位置的树状结构
func (Location) AreaLocation(c *gin.Context) {
	withoutLocation := false
	if _, ok := c.GetQuery("without_location"); ok {
		withoutLocation = true
	}

	level := int64(0)
	level, _ = strconv.ParseInt(c.Query("level"), 10, 64)

	enableQueryAll := false
	if enableQueryAllStr, ok := c.GetQuery("enable_query_all"); ok {
		var err error
		enableQueryAll, err = strconv.ParseBool(enableQueryAllStr)
		if err != nil {
			response.JSON(c, nil, errorx.New("参数错误: enable_query_all invalid", -1))
			return
		}
	}

	res, err := location.AreaLocationHasDeviceList(c.GetString("merchant_id"), c.GetString("merchant_path"), c.Query("merchant_ids"),
		withoutLocation, int(level), enableQueryAll)
	response.JSON(c, res, err)
}

func (Location) AreaLocationReal(c *gin.Context) {
	withoutLocation := false
	if _, ok := c.GetQuery("without_location"); ok {
		withoutLocation = true
	}
	level := int64(0)
	level, _ = strconv.ParseInt(c.Query("level"), 10, 64)
	res, err := location.AreaLocationHasDeviceList(c.GetString("merchant_id"),
		c.GetString("merchant_path"), c.Query("merchant_ids"),
		withoutLocation, int(level), false)

	response.JSON(c, res, err)
}

// Add 新增位置
func (Location) Add(c *gin.Context) {
	var params struct {
		ProvinceID   string  `json:"province_id"`
		CityID       string  `json:"city_id"`
		DistrictID   string  `json:"district_id"`
		Name         string  `json:"name"`
		Addr         string  `json:"addr"`
		Latitude     float64 `json:"latitude"`
		Longitude    float64 `json:"longitude"`
		OpeningHours string  `json:"opening_hours"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	id, err := location.AddLocation(
		params.ProvinceID,
		params.CityID,
		params.DistrictID,
		params.Name,
		params.Addr,
		params.Latitude,
		params.Longitude,
		params.OpeningHours,
	)
	response.JSON(c, gin.H{
		"id": id,
	}, err)
}

// Delete 删除位置
func (Location) Delete(c *gin.Context) {
	var params struct {
		LocationID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.DeleteLocation(params.LocationID)
	response.JSON(c, nil, err)
}

// Edit 编辑位置
func (Location) Edit(c *gin.Context) {
	var params struct {
		ID           string  `json:"id"`
		ProvinceID   string  `json:"province_id"`
		CityID       string  `json:"city_id"`
		DistrictID   string  `json:"district_id"`
		Name         string  `json:"name"`
		Addr         string  `json:"addr"`
		Latitude     float64 `json:"latitude"`
		Longitude    float64 `json:"longitude"`
		OpeningHours string  `json:"opening_hours"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.EditLocation(
		params.ID,
		params.ProvinceID,
		params.CityID,
		params.DistrictID,
		params.Name,
		params.Addr,
		params.Latitude,
		params.Longitude,
		params.OpeningHours,
	)
	response.JSON(c, nil, err)
}

// UploadBrandLogo 上传品牌logo
func (Location) UploadBrandLogo(c *gin.Context) {
	url, err := upload.UploadFile(c, path.Join(config.Config.FileSaveDir, "brand"))
	if err != nil {
		response.JSON(c, nil, err)
		return
	}
	response.JSON(c, map[string]interface{}{
		"url": url,
	}, nil)
}

// UploadNavImg 上传导航地图
func (Location) UploadNavMap(c *gin.Context) {
	url, err := upload.UploadFile(c, path.Join(config.Config.FileSaveDir, "nav"))
	if err != nil {
		response.JSON(c, nil, err)
		return
	}
	response.JSON(c, map[string]interface{}{
		"url": url,
	}, nil)
}

// AddFloor 新增楼层
func (Location) AddFloor(c *gin.Context) {
	var params struct {
		LocationID string `json:"location_id"`
		Name       string `json:"name"`
		Sort       int    `json:"sort"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	floorID, err := location.Floor{}.AddFloor(params.LocationID, params.Name, params.Sort)
	response.JSON(c, map[string]interface{}{
		"id": floorID,
	}, err)
}

// EditFloor 编辑楼层
func (Location) EditFloor(c *gin.Context) {
	var params struct {
		ID   string `json:"id"`
		Name string `json:"name"`
		Sort int    `json:"sort"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Floor{}.EditFloor(params.ID, params.Name, params.Sort)
	response.JSON(c, nil, err)
}

// DeleteFloor 删除楼层
func (Location) DeleteFloor(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Floor{}.DeleteFloor(params.ID)
	response.JSON(c, nil, err)
}

// FloorList 楼层列表
func (Location) FloorList(c *gin.Context) {
	var params struct {
		LocationID string `json:"location_id"`
		Page       int    `json:"page"`
		Limit      int    `json:"limit"`
		Name       string `json:"name"`
	}
	params.LocationID = c.Query("location_id")
	params.Page, _ = strconv.Atoi(c.Query("page"))
	params.Limit, _ = strconv.Atoi(c.Query("limit"))
	params.Name = c.Query("name")
	list, total, err := location.Floor{}.List(params.LocationID, params.Page, params.Limit, params.Name)
	response.JSON(c, map[string]interface{}{
		"list":  list,
		"total": total,
	}, err)
}

// FloorDetail 楼层详情
func (Location) FloorDetail(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	detail, err := location.Floor{}.Detail(params.ID)
	response.JSON(c, detail, err)
}

// FloorDetail 楼层品牌列表
func (Location) FloorBrandList(c *gin.Context) {
	locationID := c.Query("location_id")
	floorID := c.Query("floor_id")
	brands, err := location.Robot{}.GetFloorBrandList("", locationID, floorID)
	response.JSON(c, brands, err)
}

// 新增楼层品牌 AddFloorBrand
func (Location) AddFloorBrand(c *gin.Context) {
	var params struct {
		FloorID string `json:"floor_id"`
		BrandID string `json:"brand_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Floor{}.AddBrand(params.FloorID, params.BrandID)
	response.JSON(c, nil, err)
}

// 编辑楼层品牌
func (Location) EditFloorBrand(c *gin.Context) {
	var params struct {
		BindID       string `json:"bind_id"`
		FloorID      string `json:"floor_id"`
		BrandID      string `json:"brand_id"`
		ContactPhone string `json:"contact_phone"`
		ShopNO       string `json:"shop_no"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Floor{}.EditBrand(params.BindID, params.FloorID, params.BrandID, params.ContactPhone, params.ShopNO)
	response.JSON(c, nil, err)
}

// 删除楼层品牌
func (Location) DeleteFloorBrand(c *gin.Context) {
	var params struct {
		FloorID string `json:"floor_id"`
		BrandID string `json:"brand_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Floor{}.DeleteBrand(params.FloorID, params.BrandID)
	response.JSON(c, nil, err)
}

// SetBrandRecommended 设置品牌推荐
func (Location) SetBrandRecommended(c *gin.Context) {
	var params struct {
		FloorID     string `json:"floor_id"`
		BrandID     string `json:"brand_id"`
		Recommended int    `json:"recommended"`
		Sort        int    `json:"sort"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Floor{}.BrandRecommend(params.FloorID, params.BrandID, params.Recommended, params.Sort)
	response.JSON(c, nil, err)
}

// 设置品牌搜索推荐
func (Location) SetBrandSearchRecommended(c *gin.Context) {
	var params struct {
		FloorID     string `json:"floor_id"`
		BrandID     string `json:"brand_id"`
		Recommended int    `json:"recommended"`
		Sort        int    `json:"sort"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Floor{}.BrandSearchRecommend(params.FloorID, params.BrandID, params.Recommended, params.Sort)
	response.JSON(c, nil, err)
}

// 获取品牌推荐
func (Location) GetBrandRecommended(c *gin.Context) {
	recommended := -1
	robotID := c.Query("robot_id")
	locationID := c.Query("location_id")
	if val, ok := c.GetQuery("recommended"); ok && val != "" {
		recommended, _ = strconv.Atoi(val)
	}
	list, err := location.Floor{}.GetRecommendedBrand(robotID, locationID, recommended)
	response.JSON(c, list, err)
}

// 获取品牌索索推荐
func (Location) GetBrandSearchRecommended(c *gin.Context) {
	searchRecommended := -1
	robotID := c.Query("robot_id")
	locationID := c.Query("location_id")
	if val, ok := c.GetQuery("search_recommended"); ok && val != "" {
		searchRecommended, _ = strconv.Atoi(val)
	}
	list, err := location.Floor{}.GetSearchRecommendedBrand(robotID, locationID, searchRecommended)
	response.JSON(c, list, err)
}

// AddBrand 新增品牌
func (Location) AddBrand(c *gin.Context) {
	var params struct {
		Name         string `json:"name"`
		Logo         string `json:"logo"`
		Desc         string `json:"desc"`
		LocationID   string `json:"location_id"`
		FloorID      string `json:"floor_id"`
		ContactPhone string `json:"contact_phone"`
		ShopNO       string `json:"shop_no"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	id, err := location.Brand{}.AddBrand(
		params.Name,
		params.Logo,
		params.Desc,
		params.LocationID,
		params.FloorID,
		params.ContactPhone,
		params.ShopNO,
	)
	response.JSON(c, map[string]interface{}{
		"id": id,
	}, err)
}

// EditBrand 编辑品牌
func (Location) EditBrand(c *gin.Context) {
	var params struct {
		ID           string `json:"id"`
		Name         string `json:"name"`
		Logo         string `json:"logo"`
		Desc         string `json:"desc"`
		FloorID      string `json:"floor_id"`
		ContactPhone string `json:"contact_phone"`
		ShopNO       string `json:"shop_no"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Brand{}.EditBrand(
		params.ID,
		params.Name,
		params.Logo,
		params.Desc,
		params.FloorID,
		params.ContactPhone,
		params.ShopNO,
	)
	response.JSON(c, nil, err)
}

// 开启位置导航
func (Location) EnableLocationNav(c *gin.Context) {
	var params struct {
		LocationID string `json:"location_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.EnableLocationNav(params.LocationID)
	response.JSON(c, nil, err)
}

// 位置导航列表
func (Location) LocationNavList(c *gin.Context) {
	locationID := c.Query("location_id")
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	list, total, err := location.LocationNavList(locationID, page, limit)
	response.JSON(c, map[string]interface{}{
		"list":  list,
		"total": total,
	}, err)
}

// DownloadBrandTemplate 下载品牌批量导入模板
func (Location) DownloadBrandTemplate(c *gin.Context) {
	f := location.Brand{}.DownloadBrandTemplate()
	c.Header("Content-Type", "application/octet-stream")
	c.Header("content-disposition", "attachment; filename=\""+"import-brands.xlsx"+"\"")
	f.WriteTo(c.Writer)
}

// ImportBrands 批量导入品牌
func (Location) ImportBrands(c *gin.Context) {
	locationID := c.PostForm("location_id")
	file, err := c.FormFile("file")
	if err != nil {
		response.JSON(c, nil, errorx.New("获取上传文件失败", -1))
		return
	}
	f, err := file.Open()
	if err != nil {
		response.JSON(c, nil, errorx.New("上传文件内容有误", -1))
		return
	}
	defer f.Close()
	successCount, failedBrands, err := location.Brand{}.ImportBrands(locationID, f)
	response.JSON(c, map[string]interface{}{
		"success_count": successCount,
		"failed_brands": failedBrands,
	}, err)
}

// UpdateBrands 批量更新品牌
func (Location) UpdateLocationBrands(c *gin.Context) {
	var params struct {
		BrandIDs string `json:"brand_ids"`
		FloorID  string `json:"floor_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	successCount, err := location.UpdateLocationBrands(params.BrandIDs, params.FloorID)
	response.JSON(c, map[string]interface{}{
		"success_count": successCount,
	}, err)
}

// DeleteBrand 删除品牌
func (Location) DeleteBrand(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Brand{}.DeleteBrand(params.ID)
	response.JSON(c, nil, err)
}

// BrandList 品牌列表
func (Location) BrandList(c *gin.Context) {
	var params struct {
		Page       int    `json:"page"`
		Limit      int    `json:"limit"`
		Name       string `json:"name"`
		LocationID string `json:"location_id"`
	}
	params.Page, _ = strconv.Atoi(c.Query("page"))
	params.Limit, _ = strconv.Atoi(c.Query("limit"))
	params.Name = c.Query("name")
	params.LocationID = c.Query("location_id")
	list, total, err := location.Brand{}.List(params.Page, params.Limit, params.Name, params.LocationID)
	response.JSON(c, map[string]interface{}{
		"list":  list,
		"total": total,
	}, err)
}

// BrandDetail 品牌详情
func (Location) BrandDetail(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	params.ID = c.Query("id")
	brand, err := location.Brand{}.Detail(params.ID)
	response.JSON(c, brand, err)
}

// AddPosition 新增位置点
func (Location) AddPosition(c *gin.Context) {
	var params struct {
		FloorID      string  `json:"floor_id"`
		Name         string  `json:"name"`
		PositionX    float64 `json:"position_x"`
		PositionY    float64 `json:"position_y"`
		PositionType int     `json:"position_type"`
		BrandID      string  `json:"brand_id"`
		Keywords     string  `json:"keywords"`
		Latitude     float64 `json:"latitude"`
		Longitude    float64 `json:"longitude"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	positionID, err := location.FloorPosition{}.AddPostion(
		params.FloorID,
		params.Name,
		params.PositionX,
		params.PositionY,
		params.PositionType,
		params.BrandID,
		params.Keywords,
	)
	response.JSON(c,
		map[string]interface{}{
			"id": positionID,
		}, err)
}

// EditPosition 编辑位置点
func (Location) EditPosition(c *gin.Context) {
	var params struct {
		ID           string  `json:"id"`
		Name         string  `json:"name"`
		PositionX    float64 `json:"position_x"`
		PositionY    float64 `json:"position_y"`
		PositionType int     `json:"position_type"`
		BrandID      string  `json:"brand_id"`
		Keywords     string  `json:"keywords"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.FloorPosition{}.EditPosistion(
		params.ID,
		params.Name,
		params.PositionX,
		params.PositionY,
		params.PositionType,
		params.BrandID,
		params.Keywords,
	)
	response.JSON(c, nil, err)
}

// DeletePosition 删除位置点
func (Location) DeletePosition(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.FloorPosition{}.DeletePosition(params.ID)
	response.JSON(c, nil, err)
}

// PositionList 位置点列表
func (Location) PositionList(c *gin.Context) {
	positionName := c.Query("position_name")
	brandName := c.Query("brand_name")
	robotID := c.Query("robot_id")
	locationID := c.Query("location_id")
	floorID := c.Query("floor_id")
	positionType := c.Query("type")
	list, err := location.FloorPosition{}.List(
		robotID,
		locationID,
		floorID,
		positionType,
		positionName,
		brandName,
		true,
	)
	response.JSON(c, list, err)
}

// PositionDetail 位置点详情
func (Location) PositionDetail(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	position, err := location.FloorPosition{}.Detail(params.ID)
	if err != nil {
		response.JSON(c, nil, err)
	} else {
		response.JSON(c, position, nil)
	}
}

// AddStartPosition 新增起始点
func (Location) AddPositionDevice(c *gin.Context) {
	var params struct {
		RobotID    string `json:"robot_id"`
		PositionID string `json:"position_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.FloorPosition{}.BindDevice(params.RobotID, params.PositionID)
	response.JSON(c, nil, err)
}

// DeletePositionDevice 删除起始点
func (Location) DeletePositionDevice(c *gin.Context) {
	var params struct {
		RobotID string `json:"robot_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.FloorPosition{}.DeleteBindDevice(params.RobotID)
	response.JSON(c, nil, err)
}

// StartPositionList 位置点关联设备
func (Location) PositionDeviceList(c *gin.Context) {
	list := location.FloorPosition{}.DeviceList(c.Query("floor_id"))
	response.JSON(c, list, nil)
}

// NavList 导航列表
func (Location) NavList(c *gin.Context) {
	var params struct {
		Page       int    `json:"page"`
		Limit      int    `json:"limit"`
		LocationID string `json:"location_id"`
		FloorID    string `json:"floor_id"`
	}
	params.Page, _ = strconv.Atoi(c.Query("page"))
	params.Limit, _ = strconv.Atoi(c.Query("limit"))
	params.LocationID = c.Query("location_id")
	params.FloorID = c.Query("floor_id")
	total, list := location.Nav{}.List(params.LocationID, params.FloorID, params.Page, params.Limit)
	response.JSON(c, map[string]interface{}{
		"total": total,
		"list":  list,
	}, nil)
}

// DeleteNav 删除导航
func (Location) DeleteNav(c *gin.Context) {
	var params struct {
		FloorID string `json:"floor_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Nav{}.DeleteNav(params.FloorID)
	response.JSON(c, nil, err)
}

// SetNavMap 设置导航地图
func (Location) SetNavMap(c *gin.Context) {
	var params struct {
		FloorID string `json:"floor_id"`
		Map     string `json:"map"`
		NavName string `json:"nav_name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Nav{}.SetNavMap(params.FloorID, params.Map, params.NavName)
	response.JSON(c, nil, err)
}

// AddNavPath 新增导航路径
func (Location) AddNavPath(c *gin.Context) {
	var params struct {
		FloorID string `json:"floor_id"`
		Path    string `json:"path"`
		Name    string `json:"name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	pathID, err := location.Nav{}.AddPath(params.FloorID, params.Path, params.Name)
	response.JSON(c, map[string]interface{}{
		"id": pathID,
	}, err)
}

// DeleteNavPath 删除导航路径
func (Location) DeleteNavPath(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Nav{}.DeletePath(params.ID)
	response.JSON(c, nil, err)
}

// ResetNavPath 重置导航路径
func (Location) ResetNavPath(c *gin.Context) {
	var params struct {
		FloorID string `json:"floor_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Nav{}.ResetPath(params.FloorID)
	response.JSON(c, nil, err)
}

// NavPathList 导航路径列表
func (Location) NavPathList(c *gin.Context) {
	floorID := c.Query("floor_id")
	paths, err := location.Nav{}.PathList(floorID)
	response.JSON(c, paths, err)
}

// GetShortestPath 获取最短路径
func (Location) GetShortestPath(c *gin.Context) {
	robotID := c.Query("robot_id")
	startPositionID := c.Query("start_position_id")
	dstPositionID := c.Query("dst_position_id")
	dstFloorID := c.Query("dst_floor_id")
	data, err := location.Nav{}.GetShortestPath(robotID, startPositionID, dstPositionID, dstFloorID)
	response.JSON(c, data, err)
}

type LocalQA struct{}

// AddLib 创建词库
func (LocalQA) AddLib(c *gin.Context) {
	var params struct {
		Name string `json:"name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	id, err := location.LocalQA{}.AddLib(c.Request.Context(), params.Name, c.GetString("merchant_id"))
	response.JSON(c, map[string]interface{}{
		"id": id,
	}, err)
}

// UpdateLib 更新词库
func (LocalQA) UpdateLib(c *gin.Context) {
	var params struct {
		ID   string `json:"id"`
		Name string `json:"name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.LocalQA{}.UpdateLib(
		c.Request.Context(),
		params.ID,
		params.Name,
		c.GetString("merchant_id"),
	)
	response.JSON(c, nil, err)
}

// DeleteLib 删除词库
func (LocalQA) DeleteLib(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.LocalQA{}.DeleteLib(c.Request.Context(), params.ID, c.GetString("merchant_id"))
	response.JSON(c, nil, err)
}

// LibList 词库列表
func (LocalQA) LibList(c *gin.Context) {
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	list, total, err := location.LocalQA{}.LibList(
		c.Request.Context(),
		c.Query("name"),
		c.GetString("merchant_id"),
		page, limit,
	)
	response.JSON(c, map[string]interface{}{
		"list":  list,
		"total": total,
	}, err)
}

// LibDetail 词库详情
func (LocalQA) LibDetail(c *gin.Context) {
	detail, err := location.LocalQA{}.LibDetail(
		c.Request.Context(),
		c.Query("id"),
		c.GetString("merchant_id"),
	)
	response.JSON(c, map[string]interface{}{
		"detail": detail,
	}, err)
}

// BindDevice 绑定设备
func (LocalQA) BindDevice(c *gin.Context) {
	var params struct {
		LibID   string `json:"lib_id"`   // 词库id
		RobotID string `json:"robot_id"` // 设备id，多个以逗号分隔
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	robotIDs := []string{}
	if params.RobotID != "" {
		robotIDs = strings.Split(params.RobotID, ",")
	}
	_, err := location.LocalQA{}.BindDevice(c.Request.Context(), dal.Q, params.LibID, robotIDs)
	response.JSON(c, nil, err)
}

// ImportLocalQA 导入本地词库
func (LocalQA) ImportQA(c *gin.Context) {
	libID := c.PostForm("lib_id")
	file, err := c.FormFile("file")
	if err != nil {
		response.JSON(c, nil, errorx.New("获取上传文件失败", -1))
		return
	}
	f, err := file.Open()
	if err != nil {
		response.JSON(c, nil, errorx.New("上传文件内容有误", -1))
		return
	}
	defer f.Close()
	total, err := location.LocalQA{}.ImportQA(c.Request.Context(), libID, c.GetString("merchant_id"), f)
	response.JSON(c, map[string]interface{}{
		"total": total,
	}, err)
}

// GetAnswer 获取问答答案
func (LocalQA) GetAnswer(c *gin.Context) {
	var params struct {
		RobotID  string `json:"robot_id"`
		Question string `json:"question"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	answer := location.LocalQA{}.Answer(c.Request.Context(), params.RobotID, params.Question)
	response.JSON(c, map[string]interface{}{
		"answer": answer,
	}, nil)
}

// 新增位置标签
func (Location) AddLocationTag(c *gin.Context) {
	var params struct {
		Name string `json:"name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	id, err := location.Tag{}.AddLocationTag(
		c.Request.Context(),
		params.Name,
		c.GetString("merchant_id"),
	)
	response.JSON(c, map[string]interface{}{
		"id": id,
	}, err)
}

// 更新位置标签
func (Location) UpdateLocationTag(c *gin.Context) {
	var params struct {
		ID   string `json:"id"`
		Name string `json:"name"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Tag{}.UpdateLocationTag(
		c.Request.Context(),
		params.ID, params.Name,
		c.GetString("merchant_id"),
	)
	response.JSON(c, nil, err)
}

// 删除位置标签
func (Location) DeleteLocationTag(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Tag{}.DeleteLocationTag(
		c.Request.Context(),
		params.ID,
		c.GetString("merchant_id"),
	)
	response.JSON(c, nil, err)
}

// 位置标签列表
func (Location) LocationTagList(c *gin.Context) {
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	list, total, err := location.Tag{}.LocationTagList(
		c.Request.Context(),
		c.Query("name"),
		c.GetString("merchant_id"),
		page, limit,
	)
	response.JSON(c, map[string]interface{}{
		"list":  list,
		"total": total,
	}, err)
}

// 新增位置标签关联
func (Location) AddLocationTagAssociation(c *gin.Context) {
	var params struct {
		LocationID string `json:"location_id"`
		TagID      string `json:"tag_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	ids, err := location.Tag{}.AddLocationTagAssociation(c.Request.Context(), params.LocationID, params.TagID)
	response.JSON(c, map[string]interface{}{
		"ids": ids,
	}, err)
}

// 移除位置标签关联
func (Location) DeleteTagLocationAssociation(c *gin.Context) {
	var params struct {
		LocationID string `json:"location_id"`
		TagID      string `json:"tag_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.Tag{}.DeleteLocationTagAssociation(
		c.Request.Context(),
		strings.Split(params.LocationID, ","),
		params.TagID,
	)
	response.JSON(c, nil, err)
}

// 标签位置列表
func (Location) TagLocationList(c *gin.Context) {
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	list, total, err := location.Tag{}.TagLocationList(
		c.Request.Context(),
		c.Query("id"),
		c.Query("location_name"),
		page, limit,
	)
	response.JSON(c, map[string]interface{}{
		"list":  list,
		"total": total,
	}, err)
}

// 商场服务
type MallService struct{}

// Open 开通商场服务
func (MallService) Open(c *gin.Context) {
	var params struct {
		LocationID string `json:"location_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.MallService{}.Open(c.Request.Context(), params.LocationID)
	response.JSON(c, nil, err)
}

// Close 商场服务关闭
func (MallService) Close(c *gin.Context) {
	var params struct {
		LocationID string `json:"location_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.MallService{}.Close(c.Request.Context(), params.LocationID)
	response.JSON(c, nil, err)
}

// OpenStatus 商场服务开通状态
func (MallService) OpenStatus(c *gin.Context) {
	status := location.MallService{}.OpenStatus(c.Request.Context(), c.Query("robot_id"), c.Query("location_id"))
	response.JSON(c, map[string]interface{}{
		"status": status,
	}, nil)
}

// LocationList 已开通商场服务的商场
func (MallService) LocationList(c *gin.Context) {
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	records, count := location.MallService{}.LocationList(
		c.Request.Context(),
		c.Query("location_name"),
		page,
		limit,
	)
	response.JSON(c, map[string]interface{}{
		"list":  records,
		"total": count,
	}, nil)
}

// List 商场服务列表
func (MallService) List(c *gin.Context) {
	serviceType, _ := strconv.Atoi(c.Query("type"))
	status, _ := strconv.Atoi(c.Query("status"))
	records := location.MallService{}.List(
		c.Request.Context(),
		c.Query("robot_id"),
		c.Query("location_id"),
		serviceType, status,
	)
	response.JSON(c, map[string]interface{}{
		"list":  records,
		"total": len(records),
	}, nil)
}

// Add 添加服务项目
func (MallService) Add(c *gin.Context) {
	var params struct {
		LocationID string `json:"location_id"`
		Name       string `json:"name"`
		Type       int    `json:"type"`
		Logo       string `json:"logo"`
		Order      int    `json:"order"`
		Detail     string `json:"detail"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.MallService{}.Add(c.Request.Context(), []*models.MallService{
		{
			LocationID: params.LocationID,
			Name:       params.Name,
			Type:       params.Type,
			Logo:       params.Logo,
			Order:      params.Order,
			Detail:     params.Detail,
		},
	})
	response.JSON(c, nil, err)
}

// Update 更新服务项目
func (MallService) Update(c *gin.Context) {
	var params models.MallService
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.MallService{}.Update(c.Request.Context(), &params)
	response.JSON(c, nil, err)
}

// Delete 更新服务项目
func (MallService) Delete(c *gin.Context) {
	var params struct {
		ID string `json:"id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.MallService{}.Delete(c.Request.Context(), params.ID)
	response.JSON(c, nil, err)
}

// QAList 商场服务问题列表
func (MallService) QAList(c *gin.Context) {
	list, _ := location.MallServiceQA{}.List(c.Request.Context(), c.Query("service_id"))
	response.JSON(c, gin.H{
		"list": list,
	}, nil)
}

// QAAdd 商场服务新增问题
func (MallService) QAAdd(c *gin.Context) {
	var params struct {
		ServiceID string `json:"service_id"`
		Question  string `json:"question"`
		Answer    string `json:"answer"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.MallServiceQA{}.Add(c.Request.Context(), params.ServiceID, params.Question, params.Answer)
	response.JSON(c, nil, err)
}

// QAUpdate 商场服务更新问题
func (MallService) QAUpdate(c *gin.Context) {
	var params struct {
		QuestionID string `json:"question_id"`
		Question   string `json:"question"`
		Answer     string `json:"answer"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.MallServiceQA{}.Update(c.Request.Context(), params.QuestionID, params.Question, params.Answer)
	response.JSON(c, nil, err)
}

// QADelete 商场服务删除问题
func (MallService) QADelete(c *gin.Context) {
	var params struct {
		QuestionID string `json:"question_id"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	err := location.MallServiceQA{}.Delete(c.Request.Context(), params.QuestionID)
	response.JSON(c, nil, err)
}
